<script setup>

/**
 * @name: 通用DIY模板
 * @Author: flashme.cn 
 * @Date: 2024-09-23
 * @description: 
 * ├── /组件目录/ 
 * │ ├ index.vue （组件配置入口文件） 
 * │ ├ config.js （组件数据结构） 
 * │ └ module.vue （组件模块 呈现文件） 
 * ├─ config.js （按钮配置） 
 * ├─ select.vue （定义可选链接类型）
 * ├─ index.vue （后台入口文件） 
 * ├─ mobile.vue （可拖拽组件模块 - 配置时使用） 
 * ├─ module.vue （组件模块 - 项目引用呈现文件） 
 * ├─ view.vue （前端项目引用示例） 
 * ├─ link.js （组件链接出口） 
 * └─ unit.js （单位） 
 */
import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick, markRaw, defineAsyncComponent, computed } from 'vue'
import { store } from '@/js/store.js'
import { VueDraggable } from 'vue-draggable-plus'

import modeUpimg from '@/components/mode-upimg.vue';
import material from '@/components/material.vue';
import { menulist } from './config.js'
import mobileDraggable from './mobile.vue';

const props = defineProps({
    form: {
        type: Object,
        default: {}
    },
    method: String,
});
//需要响应式时使用toRefs
// const { form, method } = toRefs(props);

//向父级传递消息
const emits = defineEmits(['tohost'])
function sindEmit() {
    emits('tohost', ...arguments);
}


const vueFiles = import.meta.glob(`/src/pages/diymobile/**/module.vue`);
// views对象
const views = ref({});
for (const [key, promise] of Object.entries(vueFiles)) {
    const fileName = key.split('/').slice(-2)[0];
    // 将组件转换为异步组件并标记为原始对象（防止复用带来的副作用）
    views.value[fileName] = markRaw(defineAsyncComponent(() => promise()));
}
const vueFiles2 = import.meta.glob(`/src/pages/diymobile/**/index.vue`);
// views对象
const viewsConfig = ref({});
for (const [key, promise] of Object.entries(vueFiles2)) {
    const fileName = key.split('/').slice(-2)[0];
    // 将组件转换为异步组件并标记为原始对象（防止复用带来的副作用）
    viewsConfig.value[fileName] = markRaw(defineAsyncComponent(() => promise()));
}

//需要的配置
const configobj = {name:'模板',state:true,srcoll:true, color:'#333333', padding1:5,padding2:10}
const config = ref(configobj);
const mobileConfig = ref([])

function clone(element) {
    activeRow.value = {}
    var obj = {
        key: element.path+Math.random().toString(36).slice(-5),
        title: `${element.title}-${mobileConfig.value.length+1}`,
        path: element.path,
        icon: element.icon,
    }
    nextTick(() => {
        activeRow.value = obj
    })
    return obj
}

const activeRow = ref({});
function removeActive() {
    activeRow.value = {};
    store.screenTop = screenTop;
    store.screenHeight = screenHeight;
}

function onDragStart() {
    // activeRow.value.key = ''
}

const pcShow = ref(false);
// const historyNum = ref(0)
// var historyArr = []
// function historyEdit() {
//     historyArr.unshift(JSON.parse(JSON.stringify(mobileConfig.value)))
//     historyNum.value = 0;
//     if(historyArr.length>10){
//         historyArr.pop();
//     }
// }
// function onHistory(e) {
//     if(e==0 && historyNum.value<historyArr.length-1){
//         historyNum.value++;
//         mobileConfig.value = historyArr[historyNum.value];
//     }else if(e==1 && historyNum.value>0){
//         historyNum.value--;
//         mobileConfig.value = historyArr[historyNum.value];
//     }
// }

//=========================屏幕滚动事件

const mobileScroll = ref(null)
var screenTop = 0, screenHeight = 0;
function onScroll(event) {
    config.value.srcoll && (store.srcollTop = mobileScroll.value.scrollTop);
}
onMounted(()=>{
    nextTick(()=>{
        store.screenTop = screenTop = mobileScroll.value.getBoundingClientRect().top;//窗口容器的位置（演示窗口需设置）
        store.screenHeight = screenHeight = mobileScroll.value.clientHeight;
        mobileScroll.value.scrollTop = 0;
        mobileScroll.value.addEventListener('scroll', onScroll);
    })
})
onBeforeUnmount(()=>{
    mobileScroll.value.removeEventListener('scroll', onScroll);
})

//=========================查询数据


//监听变化
watch(() => props.form, (newVal, oldValue) => {
    // historyArr = [];
    pcShow.value = false;
    config.value = props.method=='edit'?(newVal||{}):configobj;
    mobileConfig.value = props.method=='edit'?(config.value.template||[]):[];
    activeRow.value = {}
    nextTick(()=>{
        store.screenTop = screenTop;
        store.screenHeight = screenHeight;
        mobileScroll.value.scrollTop = 0;
    });
},{
    immediate: true // 组件创建时立即执行
})

// 提交
function onSubmit(ev) {
    config.value.template = mobileConfig.value;
    sindEmit(config.value, ev);
}

const predefineColors = ref([
    '#666666',
    '#333333',
    '#000000',
    '#ffffff',
    '#f2f2f2',
    '#eeeeee',
    '#f2f7fa',
    '#006CBE',
    '#040E3B',
    '#AB0000'
])

const menu = ref(menulist)

const bgs = ref([{ url: config.value.bg }]);
watch(bgs, (newBgs) => {
    if (newBgs.length > 0) {
        config.value.bg = newBgs[0].url;
    }else{
        config.value.bg = ''
    }
  },
  { deep: true } // 深度监听
);

function onClose() {
    sindEmit(null, {close:true})
}



</script>

<template>
    <div class="flexrow row-start boxmain">
        <div class="con-left innerbox">
            <dl class="menulist" v-for="(item, index) in menu">
                <dt>{{ item.title }}</dt>
                <VueDraggable class="flexrow justify-start" tag="dd" 
                v-model="item.children" animation="150" :group="{ name: 'people', pull: 'clone', put: false }" :clone="clone" :sort="false" @start="onDragStart">
                    <div :class="['menubtn','dragmove',{active:btn.path==activeRow.path}]" v-for="(btn, n) in item.children" :key="btn.path">
                        <i :class="['fa', btn.icon]"></i><br>
                        <span>{{ btn.title }}</span>
                    </div>
                </VueDraggable>
            </dl>
        </div>
        <div class="flex1" style="background-color: aliceblue">
            <div class="tools flexrow justify-start">
                <el-button type="primary" @click="onSubmit">保存</el-button>
                <el-button type="primary" @click="onSubmit({viewShow:true})" plain>预览</el-button>
                <el-button type="success" @click="pcShow=!pcShow" :plain="!pcShow">{{pcShow?'PC端':'手机端'}}</el-button>
                <!-- <el-button type="success" plain @click="onHistory(0)"><i class="fa fa-mail-reply"></i></el-button>
                <el-button type="success" plain @click="onHistory(1)"><i class="fa fa-mail-forward"></i></el-button> -->
                <el-button @click="onClose">退出</el-button>
            </div>
            <div class="flexrow row-start">
                <div class="flex1 mobilecon innerbox" ref="mobileScroll" @click="removeActive">
                    <ul class="ruler selectnone" v-show="!pcShow">
                        <li></li>
                        <li style="top: 667px">iPhone 6~8</li>
                        <li style="top: 812px">iPhone X~14</li>
                    </ul>
                    <mobile-draggable :config="config" v-model="mobileConfig" :activeRow="activeRow" @update:activeRow="activeRow = $event" :views="views" :class="['mobile m-container',{ pc: pcShow }]" 
                    :style="{
                        color: config.color,
                        backgroundColor: config.backgroundColor,
                        backgroundImage: `url(${config.bg})`
                    }"></mobile-draggable>
                </div>
                <div class="sortlist wrap" v-show="!pcShow">
                    <div class="sortlist-title">页面组件</div>
                    <VueDraggable v-model="mobileConfig" animation="150" class="flex1 innerbox">
                        <div :class="['sortbox dragmove ellipsis',{active:item.key==activeRow.key}]" v-for="(item, index) in mobileConfig" :key="item.key" @click.stop="activeRow = item"><i class="fa fa-navicon"></i> {{ item.title }}</div>
                    </VueDraggable>
                    <hr style="margin: 0;">
                    <div :class="['sortbox handle',{active:!activeRow.key}]" @click="removeActive"><i class="fa fa-gear"></i> 页面设置</div>
                </div>
                <div class="con-right innerbox" v-show="!pcShow">
                    <el-form v-if="!activeRow.path" :model="config" label-width="80px">
                        <el-form-item label="模板名">
                            <el-input type="text" v-model="config.name" />
                        </el-form-item>
                        <el-form-item label="文字颜色">
                            <el-color-picker v-model="config.color" :predefine="predefineColors" />
                        </el-form-item>
                        <el-form-item label="背景颜色">
                            <el-color-picker v-model="config.backgroundColor" :predefine="predefineColors" />
                        </el-form-item>
                        <el-form-item label="背景图">
                            <!-- <el-input type="text" v-model="config.bg" /> -->
                            <mode-upimg :uplist="bgs" :action="store.api + store.uploadUrl" :maxnum="1" :options="{...store.upimgOptions}">
                                <i></i>
                                <template v-if="store.upimgOptions.online" v-slot:filepopup="modeParams">
                                    <material :modeParams="modeParams" :xuanze="true" />
                                </template>
                            </mode-upimg>（推荐尺寸：750*1334）
                        </el-form-item>
                        <el-form-item label="统一间距">
                            <p style="width: 96%;">上下：<el-slider v-model="config.padding1" :max="150" /></p>
                            <p style="width: 96%;">左右：<el-slider v-model="config.padding2" :max="150" /></p>
                        </el-form-item>
                        <el-form-item label="启用">
                            <el-switch v-model="config.state" />
                        </el-form-item>
                        <el-form-item label="滚屏事件">
                            <el-switch v-model="config.srcoll" />（将会影响部分组件绑定滚屏事件的动画）
                        </el-form-item>
                        <!-- <el-form-item label="自定义项">
                            <el-input type="text" v-model="config.define" />
                        </el-form-item> -->
                        <el-form-item label="备注">
                            <el-input type="text" v-model="config.note" />
                        </el-form-item>
                    </el-form>
                    <component v-else :is="viewsConfig[activeRow.path]" :config="activeRow" />
                </div>
            </div>
            
        </div>


    </div>

</template>

<style lang="scss" scoped>
$screen-height: 800px;
.boxmain{
    width: 100%; min-height: 50vh; max-width: 1880px; min-width: 1320px;
    margin: 0 auto;background-color: #f2f2f2;box-shadow: rgba(0,0,0,.1) 0 6px 10px;
}
.boxmain> div{height: 100%;overflow: auto;}
.con-left{width: 230px;}
.con-right{
    width: 380px; height: $screen-height; background-color: white;
    min-height: 667px; padding: 20px 10px;
}
.mobilecon{height: $screen-height; margin: 0 auto; padding: 25px 90px; margin: 0 10px; position: relative;}
.ruler{position: absolute;left: 50%;top: 25px;margin-left: 200px;width: 10px; height: 667px; background-color: #e0efff;}
.ruler li{position: absolute;left: 0; width: 25px;text-indent: 15px;color: #bbb;border-top: #ddd 1px solid;white-space: nowrap;font-size: 12px;}

.menulist{width: 100%;margin-bottom: 10px;background-color: white;}
.menulist dt{background-color: #dadada;padding: 8px 10px;font-weight: bold;}
.menulist dd{border-left: #dadada 1px solid;}
.menubtn{
    width: 33.33%; height: 80px; font-size: 13px; color: #666;
    border: #dadada 1px solid; border-width: 0 1px 1px 0;
    padding: 5px;text-align: center;
}
.menubtn i{font-size: 30px;margin-top: 10px;}
.menubtn.active{background-color: #f2f2f2;}

.mobile {
    width: 375px;min-height: 667px;margin: 0 auto;
    background-color: white; box-shadow: 5px 5px 20px rgba(0,0,0,.1);
    background-repeat: no-repeat; background-size: 100% auto; background-position: center top;
}
.mobile .menubtn{width: 100%;background-color:aquamarine;height: 30px;}
.mobile .menubtn i{font-size: 16px;margin: 0;}
.mobile.pc{width: 1200px;}

.tools{width: 100%;height: 40px; padding: 4px 10px;background-color: #e0efff;}

.sortlist{
    width: 110px;height: $screen-height;box-shadow: rgba(0,0,0,.1) 0 6px 10px; overflow: hidden;
    border-right: #ddd 1px solid;background-color: white;
}
.sortbox{width: 100%;padding: 0 1em; line-height: 2.8;border-bottom: #ddd 1px solid;color: #999;}
.sortbox i{color: #bbb;}
.sortbox.active{background-color: #e0efff;color: #333;}
.sortlist-title{width: 100%;height: 40px;line-height: 40px;padding: 0 1em;font-weight: bold;border-bottom: #ddd 1px solid;}

</style>

<style>

/* 前端共用css START */
.rowspace{height: 0;margin: 0;padding: 0;overflow: hidden;}
.itemrow{
	width: 100%;margin: 0 auto;padding: 5px 10px;
	position: relative; background-size: 100% auto;background-repeat: no-repeat;
}
.m-container{
    position: relative; background-size: 100% auto;background-repeat: no-repeat;min-height: 20px;
    display: flex;
    flex-wrap:wrap;/*换行*/
    justify-content: space-evenly;
    align-items : flex-start;
    align-content: flex-start;
}
/* 前端共用css END */

.con-right h1{width: 92%; font-size: 16px;text-align: left;margin: 0 auto 18px;}
</style>